/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package argtrust.certprop;

import argtrust.belief.*;
import java.util.Map;
import java.util.LinkedHashMap;
import java.util.Set;

import argtrust.trustnet.Agent;
import argtrust.trustnet.ITrustSemantics;

import argtrust.util.Pair;
import argtrust.measure.Measure;
import argtrust.measure.IMeasureOperators;
import argtrust.trustnet.IndirectTrust;
import argtrust.belief.IndirectBelief;

/**
 * Beliefs over facts and inference rules are computed from the indirect beliefs
 * of the agent's over the agents who are holding the facts and inference rules.
 * In the case in which multiple agents hold the same fact and inference rule,
 * a tidal-trust style average is applied to average the trust over the facts and
 * inference rules weighted by the holding agents' belief levels over the facts and
 * rules.
 * @author Yuqing Tang
 */
public class CertPropBelief implements ITrustBeliefSemantics {

    BeliefBase mBeliefBase;
    CertPropTrust mTrustSemantics;
    CertPropMeasureOperators mOperators;

    public IMeasureOperators getOperators() {
        return mOperators;
    }

    public CertPropBelief(
            BeliefBase belief_base,
            ITrustSemantics trust_semantics) {
        mBeliefBase = belief_base;
        mTrustSemantics = (CertPropTrust) trust_semantics;
        mOperators = (CertPropMeasureOperators) mTrustSemantics.getOperators();
    }
    Map<Pair<Agent, Object>, Measure> mTrustBeliefTable = new LinkedHashMap<Pair<Agent, Object>, Measure>();

    public CertPropMeasure getCertPropMeasure(Measure measure) {
        if (measure.getOpMeasure() instanceof CertPropMeasure) {
            return (CertPropMeasure) measure.getOpMeasure();
        } else {
            System.err.println(this.getClass().getName()
                    + " doesn't understand the belief/trust measure");
            if (measure == null) {
                System.err.println("The measure is null.");
            } else if (measure != null) {
                System.err.println("Measure: " + measure.getClass().getName());
            }
            return null;
        }
    }

    public Measure believe(Agent agent, Object obj) {
        Pair<Agent, Object> key = new Pair<Agent, Object>(agent, obj);
        Measure res = mTrustBeliefTable.get(key);
        if (res == null) {
            Set<Belief> belief_set = mBeliefBase.getBeliefSet(obj);
            CertPropMeasure bl = new CertPropMeasure();
            if (belief_set != null) {
                for (Belief belief : belief_set) {
                    if (agent.equals(belief.getOwner())) {
                        res = new CertPropMeasure(
                                getCertPropMeasure(
                                belief.getMeasure()));
                        mTrustBeliefTable.put(key, res);
                        return res;
                    }
                    Measure trust =
                            mTrustSemantics.trust(agent,
                            belief.getOwner());

                    CertPropMeasure concatenated =
                            mOperators.concatenate(
                            getCertPropMeasure(trust),
                            getCertPropMeasure(believe(belief.getOwner(), obj)));
                    bl = mOperators.aggregate(bl, concatenated);
                }
            }
            res = new IndirectBelief();
            ((IndirectBelief) res).setMeasure(bl);
            mTrustBeliefTable.put(key, res);
        }

        return res;
    }
}
